﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Imaging;
using System.Drawing.Imaging;
using System.IO;

namespace WebCam
{
    public partial class Form1 : Form
    {
        private bool DeviceExist = false;
        private FilterInfoCollection videoDevices;
        private VideoCaptureDevice videoSource = null;
        int Rate;
        int[,] maschis;

        public Form1()
        {
            InitializeComponent();
            timer1.Tick += new EventHandler(timer1_Tick);
            getCamList();
            //pictureBox1.Image = new Bitmap("C:/1.png");
            //pictureBox2.Image = СериализацияЧБ(new Bitmap("C:/1.png"));
        }

        void timer1_Tick(object sender, EventArgs e)
        {
            label3.Text = Rate.ToString();
            Rate = 0;
        }

        private void getCamList()
        {
            try
            {
                videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
                comboBox1.Items.Clear();
                if (videoDevices.Count == 0)
                    throw new ApplicationException();

                DeviceExist = true;
                foreach (FilterInfo device in videoDevices)
                {
                    comboBox1.Items.Add(device.Name);
                }
                comboBox1.SelectedIndex = 0; //make dafault to first cam
            }
            catch (ApplicationException)
            {
                DeviceExist = false;
                comboBox1.Items.Add("No capture device on your system");
            }
        }

        private void start_Click(object sender, EventArgs e)
        {
            if (start.Text == "&Start")
            {
                if (DeviceExist)
                {
                    timer1.Start();
                    videoSource = new VideoCaptureDevice(videoDevices[comboBox1.SelectedIndex].MonikerString);
                    //videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
                    CloseVideoSource();
                    //videoSource.DesiredFrameRate = 200;
                    //videoSource.DesiredFrameSize = new Size(pictureBox1.Width, pictureBox1.Height);
                    videoSource.DesiredFrameSize = new Size(1280, 960);
                    videoSource.DesiredFrameRate = 30;
                    //maschis = new int[videoSource.DesiredFrameSize.Width, videoSource.DesiredFrameSize.Height];                    
                    //videoSource.Start();

                    OpenVideoSource(videoSource);

                    label2.Text = "Device running...";
                    start.Text = "&Stop";
                }
                else
                {
                    label2.Text = "Error: No Device selected.";
                }
            }
            else
            {
                if (videoSource.IsRunning)
                {
                    timer1.Stop();
                    Rate = 0;
                    CloseVideoSource();
                    label2.Text = "Device stopped.";
                    start.Text = "&Start";
                }
            }
        }

        private void OpenVideoSource(IVideoSource source)
        {
            // set busy cursor
            this.Cursor = Cursors.WaitCursor;

            // close previous video source
            //CloseVideoSource();
            // start new video source
            Player.VideoSource = source;
            Player.NewFrame += new AForge.Controls.VideoSourcePlayer.NewFrameHandler(Player_NewFrame);
            Player.Start();

            // reset statistics
            //statIndex = statReady = 0;

            //videoSource = source;

            this.Cursor = Cursors.Default;
        }

        void Player_NewFrame(object sender, ref Bitmap image)
        {
            Rate++;
            int filter = 0;
            try
            {
                this.Invoke(new Action(() => { filter = trackBar1.Value; }));
            }
            catch { }
            pictureBox2.Image = СериализацияЧББыстро((Bitmap)image.Clone(), filter);
        }

        private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            Rate++;
            //Bitmap img = (Bitmap)eventArgs.Frame.Clone();
            //pictureBox3.Image = (Bitmap)eventArgs.Frame.Clone();
            //pictureBox1.Image = СериализацияОттенкиСерогоБыстро((Bitmap)eventArgs.Frame.Clone());
            int filter = 0;
            try
            { 
                this.Invoke(new Action(() => { filter = trackBar1.Value; }));
            }
            catch { }
            //pictureBox2.Image = СериализацияЧББыстро((Bitmap)eventArgs.Frame.Clone(), filter);
            //Вывод_в_файл();
            //Вывод бинаризованной матрицы в файл
            Сегментация();
            Вывод_в_файл();
        }

        private void Сегментация()
        {
            int num=1;
            for (int j = 0; j < maschis.GetLength(1)-1; j++)
            {
                for (int i = 1; i < maschis.GetLength(0); i++)
                {
                    switch (maschis[i, j])
                    {
                        case 0:
                            {
                                if (maschis[i - 1, j + 1] == 0 && maschis[i, j + 1] == 1)
                                {
                                    num++;
                                    maschis[i, j + 1] = num;
                                }
                                else if (maschis[i - 1, j + 1] != 0 && maschis[i, j + 1] == 1)
                                    maschis[i, j + 1] = maschis[i - 1, j + 1];
                            } break;
                        default:
                            {
                                if (maschis[i, j + 1] == 1)
                                {
                                    maschis[i, j + 1] = maschis[i, j];
                                }
                            } break;
                    }
                }
            }
        }

        private void Вывод_в_файл()
        {
            string maintext = "";
            for (int j = 0; j < maschis.GetLength(1); j++)
            {
                string text = "";
                for (int i = 0; i < maschis.GetLength(0); i++)
                    text += maschis[i, j];
                maintext += text + "\r\n";
            }
            //File.WriteAllText("C:/text.doc", maintext);
        }

        unsafe Bitmap СериализацияОттенкиСерогоБыстро(Bitmap bmp)
        {
            // Только 24 битные изображения
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                throw new ArgumentException();

            var bd = bmp.LockBits(
                new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.ReadWrite,
                bmp.PixelFormat
            );

            var pStart = (byte*)bd.Scan0;
            var pEnd = (byte*)(pStart + bd.Stride * bd.Height);

            while (pStart != pEnd)
            {
                // BGR
                *pStart = *(pStart + 1) = *(pStart + 2) = (byte)(0.3 * *pStart + 0.59 * *(pStart + 1)+0.11**(pStart + 2));
                pStart += 3;
            }
            bmp.UnlockBits(bd);
            return (Bitmap)bmp.Clone();
        }

        unsafe Bitmap СериализацияЧББыстро(Bitmap bmp, int filter)
        {
            // Только 24 битные изображения
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                throw new ArgumentException();

            var bd = bmp.LockBits(
                new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.ReadWrite,
                bmp.PixelFormat
            );

            var pStart = (byte*)bd.Scan0;
            var pEnd = (byte*)(pStart + bd.Stride * bd.Height);
            int i = 0;
            int j = 0;


            while (pStart != pEnd)
            {
                // BGR
                if ((*pStart + *(pStart + 1) + *(pStart + 2)) / 3 > filter)
                {
                    *pStart = *(pStart + 1) = *(pStart + 2) = 255;
                    //maschis[i, j] = 0;
                }
                else
                {
                    *pStart = *(pStart + 1) = *(pStart + 2) = 0;
                    //maschis[i, j] = 1;
                }

                pStart += 3;
                //i++;
                //if (i == bmp.Width)
                //{
                //    i = 0;
                //    j++;
                //}
            }
            bmp.UnlockBits(bd);
            return (Bitmap)bmp.Clone();
        }

        private void CloseVideoSource()
        {
            if (!(videoSource == null))
                if (videoSource.IsRunning)
                {
                    videoSource.SignalToStop();
                    videoSource = null;
                }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            CloseVideoSource();
        }
    }
}